﻿// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Pex.Framework.Packages;
using Microsoft.Pex.Engine.ComponentModel;
using Microsoft.ExtendedReflection.Metadata;
using Microsoft.Pex.Fitness.Interfaces;

namespace Microsoft.Pex.Fitness
{
    [__DoNotInstrument]
    public sealed class PexFitnessPriorityAttribute
        : PexExplorationPackageAttributeBase
    {
        private readonly Type type;
        private readonly string methodName;
        private readonly int priorityOfTarget;
        public PexFitnessPriorityAttribute(
            Type type,
            string methodName,
            int negatedPriority)
        {
            if (type == null) throw new ArgumentNullException();
            if (methodName == null) throw new ArgumentNullException();
            this.type = type;
            this.methodName = methodName;
            this.priorityOfTarget = -negatedPriority;
        }

        protected override void Initialize(IPexExplorationEngine host)
        {
            base.Initialize(host);
            var fitnessExplorationMonitor = host.GetService<IPexFitnessExplorationManager>();
            var typeDefinition = MetadataFromReflection.GetTypeDefinition(type);
            foreach (var m in typeDefinition.DeclaredInstanceMethods)
            {
                //host.Log.LogMessage("fitness", "m.ShortName {0} ~~ this.methodName {1}", m.ShortName, this.methodName);
                if (m.ShortName == this.methodName)
                    fitnessExplorationMonitor.SetUserPriority(m, this.priorityOfTarget);
            }
            foreach (var m in typeDefinition.DeclaredStaticMethods)
            {
                //host.Log.LogMessage("fitness", "Static m.ShortName {0} ~~ this.methodName {1}", m.ShortName, this.methodName);
                if (m.ShortName == this.methodName)
                    fitnessExplorationMonitor.SetUserPriority(m, this.priorityOfTarget);
            }
        }
    }
}
